<template>
  <md-menu
    class="md-select"
    :class="{ 'md-disabled': disabled }"
    :md-close-on-select="false"
    :md-active.sync="showSelect"
    :md-offset-x="offset.x"
    :md-offset-y="offset.y"
    :md-dense="mdDense"
    @md-closed="onClose"
    ref="com"
  >
    <div class="chips" @click="openSelect">
      <md-chip
        class="gg_chip"
        v-for="(chip, key) in MdSelect.array"
        :key="chip.id"
        md-deletable
        md-clickable
        :md-duplicated="false"
        @click.stop="$emit('md-click', chip, key)"
        @md-delete.stop="removeChip(chip.id, key)"
      >
        {{ chip.name }}
      </md-chip>
    </div>
    <div class="select-icon-arrow" :class="{ active: showSelect }">
      <md-drop-down-icon @click.native="toogleSelect" />
    </div>

    <keep-alive>
      <md-menu-content
        ref="menu"
        class="md-select-menu"
        :md-content-class="mdClass"
        :style="menuStyles"
        @enter="onMenuEnter"
      >
        <slot v-if="showSelect" />
      </md-menu-content>
    </keep-alive>

    <div v-if="!showSelect" v-show="false">
      <slot />
    </div>

    <input class="md-input-fake" v-model="model" :disabled="disabled" readonly tabindex="-1" />
    <select readonly v-model="model" v-bind="attributes" tabindex="-1"></select>
  </md-menu>
</template>

<script>
import MdDropDownIcon from '../common/MdDropDownIcon';
import MdMenuContent from '../common/MdMenuContent';
import MdFieldMixin from '../common/MdFieldMixin';

const defaultOffset = {
  x: 0,
  y: 0
};

export default {
  name: 'GgChipsSelect',
  components: {
    MdMenuContent,
    MdDropDownIcon
  },
  mixins: [MdFieldMixin],
  props: {
    mdDense: Boolean,
    mdClass: String,
    id: String,
    name: String
  },
  inject: ['MdField'],
  data() {
    return {
      localValue: [],
      menuStyles: {},
      offset: {
        x: defaultOffset.x,
        y: 0
      },
      showSelect: true,
      didMount: false,
      MdSelect: {
        items: {},
        label: null,
        array: [],
        multiple: true,
        modelValue: this.localValue,
        setValue: this.setValue,
        setContent: this.setContent,
        setMultipleValue: this.setMultipleValue,
        setMultipleContent: this.setMultipleContent
      }
    };
  },
  provide() {
    const MdSelect = this.MdSelect;

    return { MdSelect };
  },
  computed: {
    attrs() {
      return {
        ...this.$attrs,
        name: this.name,
        id: undefined
      };
    },
    inputListeners() {
      return {
        ...this.$listeners,
        input: undefined
      };
    }
  },
  watch: {
    localValue: {
      immediate: true,
      handler(val) {
        this.setMultipleContentByValue();
        this.MdSelect.modelValue = this.localValue;

        if (this.didMount) {
          this.emitSelected(val);
        }
      }
    }
  },
  methods: {
    removeChip(id, key) {
      const _index = this.localValue.indexOf(id);
      if (_index > -1) {
        this.localValue.splice(_index, 1);
      } else {
        this.localValue.splice(key, 1);
      }
    },
    elHasScroll(el) {
      return el.scrollHeight > el.offsetHeight;
    },
    scrollToSelectedOption(el, menu) {
      const top = el.offsetTop;
      const elHeight = el.offsetHeight;
      const menuHeight = menu.offsetHeight;

      menu.scrollTop = top - (menuHeight - elHeight) / 2;
    },
    setOffsets(target) {
      if (!this.$isServer) {
        const menu = this.$refs.menu.$refs.container;

        if (menu) {
          const selected = target || menu.querySelector('.md-selected');

          if (selected) {
            this.scrollToSelectedOption(selected, menu);
            this.offset.y = defaultOffset.y + 1;
            this.menuStyles['transform-origin'] = `0 ${Math.abs(this.offset.y)}px`;
          } else {
            this.offset.y = defaultOffset.y + 1;
            delete this.menuStyles['transform-origin'];
          }
        }
      }
    },
    onMenuEnter() {
      if (!this.didMount) {
        return;
      }

      this.setOffsets();
      this.MdField.focused = true;
      this.$emit('md-opened');
    },
    applyHighlight() {
      this.MdField.focused = false;
      this.MdField.highlighted = true;
      // this.$refs.input.$el.focus();
    },
    onClose() {
      this.$emit('md-closed');
      if (this.didMount) {
        this.applyHighlight();
      }
    },
    onFocus() {
      if (this.didMount) {
        this.applyHighlight();
      }
    },
    removeHighlight() {
      this.MdField.highlighted = false;
    },
    toogleSelect() {
      if (!this.disabled) {
        this.showSelect = !this.showSelect;
      }
    },
    openSelect() {
      if (!this.disabled) {
        this.showSelect = true;
      }
    },
    arrayAccessorRemove(arr, index) {
      let before = arr.slice(0, index);
      let after = arr.slice(index + 1, arr.length);
      return before.concat(after);
    },
    toggleArrayValue(value) {
      let index = this.localValue.indexOf(value);
      let includes = index > -1;
      if (!includes) {
        this.localValue = this.localValue.concat([value]);
      } else {
        this.localValue = this.arrayAccessorRemove(this.localValue, index);
      }
    },
    setValue(newValue) {
      this.model = newValue;
      this.setFieldValue();
      this.showSelect = false;
    },
    setArray(value) {
      this.MdSelect.array = value;
      this.setContent(value.map((v) => v.name).join(','));
    },
    setContent(newLabel) {
      this.MdSelect.label = newLabel;
    },
    setMultipleValue(value) {
      const newValue = value;
      this.toggleArrayValue(newValue);
      this.setFieldValue();
    },
    setMultipleContentByValue() {
      let content = [];

      this.localValue.forEach((item) => {
        const textContent = this.MdSelect.items[item];

        if (textContent) {
          content.push({ name: textContent, value: item });
        }
      });

      this.setArray(content);
    },
    emitSelected(value) {
      this.$emit('md-selected', value);
    }
  },
  mounted() {
    this.showSelect = false;
    if (this.value && this.value.length) {
      this.localValue = this.value;
    }

    this.$nextTick().then(() => {
      this.setMultipleContentByValue();
      this.didMount = true;
      this.menuStyles.width = this.$refs.com.$el.offsetWidth + 'px';
      this.menuStyles['max-width'] = 'none';
    });
  }
};
</script>

<style lang="less" scoped>
.chips {
  width: 100%;
  cursor: pointer;
  padding-bottom: 4px;
  .md-chip.md-deletable.md-clickable {
    height: 20px;
    line-height: 20px;
    font-size: 10px;
    color: #202124;
    margin-top: 6px;
    margin-right: 8px;
    margin-left: 0;
    background: #e0e0e0;
    > .md-ripple {
      padding-right: 30px;
    }
    /deep/ .md-button.md-input-action {
      width: 15px;
      min-width: 15px;
      height: 15px;
      .md-button-content {
        height: 11px;
        .md-icon {
          width: 11px;
          min-width: 11px;
          height: 11px;
          font-size: 11px !important;
        }
      }
    }
  }
}
.select-icon-arrow {
  width: 24px;
  height: 24px;
  overflow: hidden;
  margin-top: 4px;
  .md-icon {
    transition: transform 500ms;
    transform-origin: center;
  }
  &.active {
    .md-icon {
      transform: rotate(180deg);
    }
  }
}
</style>
